package pack.configuration;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.batch.MyBatisPagingItemReader;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import pack.PersonItemProcessor;
import pack.bean.ReadData;
import pack.bean.WriteData;

import javax.sql.DataSource;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * @author zzxx_zhangzhiwei
 * @Date 2020/10/12 2:36 下午
 * <p>
 * 任务配置类(第一个任务)
 */
@Configuration
public class HelloWorldJobConfig {


    @Bean("datasource")
    @ConfigurationProperties(prefix = "spring.datasource")
    @Primary
    public DataSource batchDatasource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * helloWorldJob任务配置
     *
     * @param jobBuilders  任务创建工厂类
     * @param stepBuilders 步骤创建工厂类
     * @return
     */
    @Bean
    public Job helloWorldJob(JobBuilderFactory jobBuilders, StepBuilderFactory stepBuilders) throws Exception {
        return jobBuilders.get("helloWorldJob")
                .start(helloWorldStep(stepBuilders)).build();
    }

    /**
     * helloWorld步骤任务配置
     *
     * @param stepBuilders 步骤创建工厂类
     * @return
     */
    @Bean
    public Step helloWorldStep(StepBuilderFactory stepBuilders) throws Exception {
        return stepBuilders.get("helloWorldStep")
                .<ReadData, WriteData>chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }


    /**
     * 获取数据方法
     * 这里使用的文件处理类(如需要读取数据库数据可使用JDBC为前缀的ReaderBuilder)
     *
     * @return
     */
//    @Bean
//    public JdbcCursorItemReader reader() {
//        String readSql = " select * from read_data";
//        JdbcCursorItemReader build = new JdbcCursorItemReader();
//        build.setDataSource(batchDatasource());
//        build.setSql(readSql);
//        build.setVerifyCursorPosition(false);
//        build.setRowMapper(new ResourceRowMapper());
//        return build;
//    }
    @Bean
    @StepScope
    public MyBatisPagingItemReader<ReadData> reader() throws Exception {
        MyBatisPagingItemReader<ReadData> itemReader = new MyBatisPagingItemReader();
        itemReader.setSqlSessionFactory(sqlSessionFactory());
        itemReader.setQueryId("pack.mysql.mapper.ReadMapper.getResourceData");
        itemReader.setPageSize(10);
        return itemReader;
    }


    /**
     * 读取数据之后的处理方法
     *
     * @return
     */
    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    /**
     * 写入方法
     * 目前配置是都区之后逐条处理,并累计到10条时进行统一写入
     *
     * @return
     */
    @Bean
    @StepScope
    public JdbcBatchItemWriter<WriteData> writer() {
        // 使用的JdbcBatchltemWriter则是通过JDBC将数据写出到一个关系型数据库中。
        JdbcBatchItemWriter writer = new JdbcBatchItemWriter();
        // 配置使用的数据源
        writer.setDataSource(batchDatasource());
        // 配置数据插入SQL，注意占位符的写法是":属性名"
        writer.setSql("insert into write_data(id,no,name) " + "values(:id,:no,:name)");
        // 最后通过BeanPropertyItemSqlParameterSourceProvider实例将实体类的属性和SQL中的占位符一一映射
        writer.setItemSqlParameterSourceProvider(
                new BeanPropertyItemSqlParameterSourceProvider<>());
        return writer;
    }


    //构造线程
    @Bean
    protected ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(15);
        executor.setKeepAliveSeconds(300);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        executor.setQueueCapacity(10000);
        executor.setThreadGroupName("spring_batch");
        return executor;
    }

    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(batchDatasource());
        return sqlSessionFactoryBean.getObject();
    }
}
